# -*- coding: utf-8 -*-            
# @Author : HJH
# @Time : 2024/1/17 16:58
# @Use :南航代理费
import concurrent
from concurrent import futures
import gzip
import json
import base64
from datetime import datetime, timedelta

import pandas as pd
import requests
from loguru import logger

URL_CZNDC = 'http://b2b.airndc.com:31830/hub2-api/ndc/airShopping'
agencyID = 'SHYA2B'
uid = 'SHYA2B'
sid = 'SHA7026'
key = 'G0TODRZ49'
accountNumber = 'SHA7026'


class ZipUtil:
    @staticmethod
    def unGzip(base64String, encoding="utf-8"):
        """对基于Base64编码的gzip压缩字符串进行解压缩"""
        # 先解码Base64字符串
        decodedData = base64.b64decode(base64String)

        # 使用gzip模块对解码后的数据进行解压缩
        try:
            uncompressedData = gzip.decompress(decodedData)

            # 转换为指定编码的字符串
            uncompressedString = uncompressedData.decode(encoding)

            return uncompressedString
        except Exception as e:
            print("解压缩失败：%s" % str(e))


def send_request(dep: str, arr: str, dep_date: str):
    timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S:%f")[:-3]
    echoToken = '-154657982198372081770826418308791437316393168888'

    params = {
        'memberInfo':
            {
                "accountNumber": f"{accountNumber}",
                "agencyID": f"{agencyID}"
            },
        "payloadAttributes":
            {
                "airlineCode": "CZ",
                "channel": "NDC",
                "echoTokenText": f"{echoToken}",
                "system": "B2B",
                "timestamp": f"{timestamp}",
                "transactionID": "999999"
            },
        "request":
            {
                "bigClientId": "20230426",
                "directOnly": True,
                "originDestinations":
                    [
                        {
                            "destCityCode": f"{arr}",
                            "origCityCode": f"{dep}",
                            "travelDate": f"{dep_date}"
                        }
                    ],
                "travelers":
                    [
                        {
                            "passengerNumber": 1,
                            "passengerType": "ADT"
                        }
                    ]
            }
    }

    headers = {
        "zone": "DOM",
        "uid": uid,
        "token": echoToken,
        "channel": "NDC",
        "airline": "CZ",
        "sid": sid
    }

    try:
        response = requests.post(URL_CZNDC, headers=headers, json=params, timeout=10000)
    except requests.Timeout as e:
        logger.error("【{} {}-{}】: {}", dep_date, dep, arr, e)
        return None
    except requests.RequestException as e:
        logger.error("【{} {}-{}】: {}", dep_date, dep, arr, e)
        return None
    # logger.info(response.text)
    response.raise_for_status()

    res = response.content.decode(response.encoding)
    if res is not None and res != '' and "{" not in res:
        res = ZipUtil.unGzip(res, "UTF-8")

    # logger.info("【南航ndc接口请求】结果: {}", res)

    res = json.loads(res)
    if res.get('status', {}).get('status') == 'FAILED' or res.get('response') is None:
        logger.error("【{} {}-{}】: {}", dep_date, dep, arr, res.get('status', {}).get('errorMessage'))
        return None

    logger.info("【{} {}-{}】: {}", dep_date, dep, arr, res['status']['status'])

    rows = []
    fare_detail_list = res["response"]["fareDetailList"]
    for fare_detail in fare_detail_list:
        row = {}
        f_c_s = fare_detail['fareComponents'][0]
        f_p_t_s = [fpt for fpt in f_c_s['farePriceTypes'] if fpt['passengerType'] == 'ADT' and fpt['totalFee'] != 0]
        f_p_t = f_p_t_s[0] if len(f_p_t_s) > 0 else None
        if f_p_t is not None:
            row['起飞日期'] = f'{dep_date}'
            row['航班号'] = f_c_s.get('offerID')[:6]
            row['起飞'] = f'{dep}'
            row['到达'] = f'{arr}'
            row['舱位'] = f_p_t['fareBasisCode']
            row['价格'] = f_p_t['baseAmount']
            row['代理费'] = f_p_t['totalFee']
            # logger.info("【数据】:" + str(row))
            rows.append(row)
    return rows


# 定义一个任务函数，即要在线程池中并发执行的逻辑
def task_function(tf_dep_date, tf_line):
    # 请求数据
    return send_request(tf_line[:3], tf_line[3:], tf_dep_date)


def get_airlines(ac_code):
    all_ac_lines = pd.read_excel(r'D:\project\git\work\python-work\docs\航线表.xlsx', sheet_name='单航司')
    return all_ac_lines[ac_code].tolist()


if __name__ == '__main__':

    # 创建线程池
    with concurrent.futures.ThreadPoolExecutor(max_workers=12) as executor:
        # 存储任务的 future 对象
        futures2 = []

        # 获取航线
        cz_lines = get_airlines('CZ')
        # cz_lines = cz_lines[:20]
        cz_lines.sort()  # 对列表进行排序
        # 获取开始日期
        dep_date = datetime.now() + timedelta(days=5)
        # 向线程池提交任务
        for i in range(30):
            dep_date_str = dep_date.strftime('%Y%m%d')
            for line in cz_lines:
                future = executor.submit(task_function, dep_date_str, line)
                futures2.append(future)
            dep_date += timedelta(days=1)

        # 定义表头
        headers = ['起飞日期', '航班号', '起飞', '到达', '舱位', '价格', '代理费']
        # 创建一个表格对象
        cz_agent_fee_df = pd.DataFrame(columns=headers)

        # 处理已完成的任务
        for future in concurrent.futures.as_completed(futures2):
            ft_rows = future.result()
            if ft_rows is not None:
                cz_agent_fee_df = cz_agent_fee_df._append(
                    pd.DataFrame([ft_row for ft_row in ft_rows], columns=cz_agent_fee_df.columns))
        cz_agent_fee_df.to_excel("CZ_Agent_Fee.xlsx", index=False)

        # 在所有任务执行完毕后执行其他代码
        logger.info("All tasks completed. Running additional code here...")
